#include "TcpConnection.h"
#include "EventLoop.h"

#include <iostream>
#include <sstream>
namespace xkk
{

TcpConnection::TcpConnection(int fd,EventLoop *loop)
    :_sock(fd)
     ,_socketIo(fd)
     ,_localAddr(getLocalAddr())
     ,_peerAddr(getPeerAddr())
     ,_isShutdownWrite(false)
     ,_loop(loop)
    {}

TcpConnection::~TcpConnection()
{
    if(!_isShutdownWrite){
        shutdown();
    }
}

string TcpConnection::receive()
{
    char buff[65536]={0};
    _socketIo.readline(buff,sizeof(buff));
    cout<<"receive data : "<<buff<<endl;
    return string(buff);
}

void TcpConnection::send(const string &msg)
{
    size_t sz=msg.size();
    _socketIo.writen(to_string(sz).c_str(),4);//先传文件大小
    _socketIo.writen(msg.c_str(),msg.size());//再传文件内容
    cout<<"send data : "<<msg<<endl;
}

void TcpConnection::sendInLoop(const string &msg)
{
    /* cout<<"sendInLoop"<<endl; */
    if(_loop)
        _loop->runInLoop(bind(&TcpConnection::send,shared_from_this(),msg));
}

void TcpConnection::shutdown()
{
    if(!_isShutdownWrite){
        _isShutdownWrite=true;
        _sock.shutdownWrite();
    }
}

string TcpConnection::toString() const
{
    std::ostringstream oss;
    oss<<_localAddr.ip()<<":"<<_localAddr.port()<<"--->"
        <<_peerAddr.ip()<<":"<<_peerAddr.port();
    return oss.str();
}

void TcpConnection::handleConnectionCallback()
{
    if(_onConnection)
        _onConnection(shared_from_this());
}
void TcpConnection::handleMessageCallback()
{
    if(_onMessage)
        _onMessage(shared_from_this());
}
void TcpConnection::handleCloseCallback()
{
    if(_onClose)
        _onClose(shared_from_this());
}

InetAddress TcpConnection::getLocalAddr()
{
    struct sockaddr_in addr;
    socklen_t len=sizeof(struct sockaddr);
    if(getsockname(_sock.fd(),(struct sockaddr*)&addr,&len)==-1){
        perror("getsockname");
    }
    return InetAddress(addr);
}
InetAddress TcpConnection::getPeerAddr()
{
    struct sockaddr_in addr;
    socklen_t len=sizeof(struct sockaddr);
    if(getpeername(_sock.fd(),(struct sockaddr*)&addr,&len)==-1){
        perror("getpeername");
    }
    return InetAddress(addr);
}

}//end of namespace xkk
